home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * B G_ G E N E S . C
- * O.F.Ransen: 15th April 1992
- * This version: 12th Feb 1993
- * This file deals with selecting the best players and changing the
- * strategy weightings of the worst one. This is in the hope that the
- * worse ones 'learn' to become better. The strategic weightings are
- * stored in a file.
- *
- */
-
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <string.h>
- #include <conio.h>
- #include <dos.h>
- #include "bg.h"
-
- /**************************************************************************/
-
- const short N_Times = 5 ; /* How many tournaments */
- extern int Target_Score ; /* To what level */
-
- extern long Weights [N_OPPS][N_WEIGHTS] ;
-
- const short Pos_Change [N_OPPS] = {0,5,10,20} ;
- /* The further down we go in the classification the more drastic the
- changes need to be to get something going. A P at the top of the
- classification has a 0% change coz he is doing well, so he changes
- nothing in his strategy */
-
- #define WF_NAME "WEIGHTS.C"
-
- /***************************************************************************/
-
- void Genetic_Selection (void)
- /*
- PURPOSE: To run several tournaments between the computer players. The
- winner of the tournament does not have his weights adjusted, while the
- losers do.
- */
- { /* Piero, Sergio, Enzo, Antonello */
- short Positions [N_OPPS] ; /* [THIRD,FIRST,LAST,SECOND] */
- short Old_Positions [N_OPPS] ;
- short Deltas [N_OPPS][N_WEIGHTS] ;
- short p,t;
-
- Read_Weights (Weights) ;
-
- Target_Score = 7 ;
- t = 0 ;
- for (p = 0 ; p < N_OPPS ; p++) {
- Positions[p] = p ; /* Initialised, but no real meaning yet */
- }
-
- Print_Tournament (t,Positions) ;
-
- t = 1 ;
- Tournament (Positions) ; /* Get an initial classification */
- Print_Tournament (t,Positions) ;
-
- /* Randomise the initial changes */
- for (p = 0 ; p < N_OPPS ; p++) {
- Randomise_Deltas (Deltas[p],Positions[p]) ;
- }
-
- for (t = 2 ; t < N_Times ; t++) {
-
- for (p = 0 ; p < N_OPPS ; p++) { /* Store old pos so we can */
- Old_Positions [p] = Positions [p] ; /* do a comparison later */
- }
-
- /* Change weights by deltas */
- for (p = 0 ; p < N_OPPS ; p++) {
- Remake_Weights (Weights[p],Deltas[p]) ;
- }
-
- Print_Tournament (t,Positions) ;
- /* Have another go */
- Tournament (Positions) ;
-
- for (p = 0 ; p < N_OPPS ; p++) {
- /* If position is better reinforce the weight change */
- Reinforce_Or_Shuffle (Deltas[p],Positions[p],Old_Positions[p]) ;
- }
- }
-
- Write_Weights (Weights,Positions) ;
- printf ("\nFinished games") ; (void)getch () ;
- Go_Text_Mode () ;
- }
-
- /***************************************************************************/
-
- void Read_Weights (long Weights[N_OPPS][N_WEIGHTS])
- /*
- PURPOSE: To read the weights of the players from a file called WEIGHTS.C.
- The file is roughly in C code format so it can be easily incorportated
- into in the program.
- */
- {
- FILE* File ;
- short p, w ;
- boolean Error = FALSE ;
-
- File = fopen (WF_NAME,"rt") ;
-
- if (File != NULL) {
- for (p = 0 ; p < N_OPPS ; p++) {
- if (fscanf (File,"{%ld",&Weights[p][0]) != 1) {
- Error = TRUE ;
- break ;
- }
- for (w = 1 ; w < N_WEIGHTS ; w++) {
- if (fscanf (File,",%ld",&Weights[p][w]) != 1) {
- Error = TRUE ;
- break ;
- }
- }
- fscanf (File,"},\n") ;
- if (Error) {
- break ;
- }
- }
- fclose (File) ;
- if (Error) {
- printf ("\nError reading %s, using predefined values",WF_NAME) ;
- }
- }
- }
-
- /***************************************************************************/
-
- void Write_Weights (long Weights [N_OPPS][N_WEIGHTS], short Positions[N_OPPS])
- /*
- PURPOSE: To write out the weights as a C array of N_OPPS rows by
- N_WEIGHTS columns. We also write out the classifications as
- passed to us in Positions.
- */
- {
- FILE* File ;
- extern String_Menu_t Setup_Menu [N_SETUP_FIELDS] ;
- short p, w ;
-
- File = fopen (WF_NAME,"wt") ;
-
- if (File == NULL) {
- printf ("\nSERIOUS ERROR: Cannot open %s for writing",WF_NAME) ;
- return ;
- }
-
- for (p = 0 ; p < N_OPPS ; p++) {
- fprintf (File,"{%5ld",Weights[p][0]) ;
- for (w = 1 ; w < N_WEIGHTS ; w++) {
- fprintf (File,",%4ld",Weights[p][w]) ;
- }
- fprintf (File,"},\n") ;
- }
-
- for (p = 0 ; p < N_OPPS ; p++) {
- fprintf (File,"\n/* %s(#%d) finished in position %d */ ",
- Setup_Menu[OPP_FIELD].Options[0][p], // Name of player
- p, // Number of player
- Positions[p]) ; // Position of player
- }
- fclose (File) ;
- }
-
- /***************************************************************************/
-
- void Reinforce_Or_Shuffle (short Deltas[N_WEIGHTS], short Pos, short Old_Pos)
- /*
- If the Pos is better than the Old_Pos then Deltas do not change coz
- we are going in the right direction. If it is equal or worse then we
- change the deltas in random directions by an amount which increases
- with worsening Pos. The idea is that the worse the position the more
- drastic the change needs to be, so Pos_Change is a list of increasing
- percentage values.
- */
- {
- if (Pos >= Old_Pos) { /* Lower down in classification, so shuffle */
- Randomise_Deltas (Deltas,Pos) ;
- }
- }
-
- /***************************************************************************/
-
- void Remake_Weights (long Weights[N_WEIGHTS], short Deltas[N_WEIGHTS])
- /*
- PURPOSE: To add the deltas to the weights, limiting the resulting
- weights from 0..100 inclusive.
- */
- {
- short w ;
-
- for (w = 0 ; w < N_WEIGHTS ; w++) {
- Weights[w] = Weights[w] + Deltas[w] ;
- if (Weights[w] < 0) {
- Weights[w] = 0 ;
- } else if (Weights[w] > 100) {
- Weights[w] = 100 ;
- }
- }
- }
-
- /***************************************************************************/
-
- void Tournament (short Pos[N_OPPS])
- /*
- PURPOSE: To run a tournament between all the players. Then the
- classification of each player is stored in Pos. e.g:
- Player_Name = Piero, Sergio, Enzo, Antonello
- = 0, 1, 2, 3
- Player_Pos = {THIRD, FIRST, LAST, SECOND}
- = { 2, 0, 3, 1}
- */
- {
- short w,b,p,i,q,Winnr,Temp;
- short Wins[N_OPPS],Ply[N_OPPS] ;
-
- for (p = 0 ; p < N_OPPS ; p++) {
- Wins[p] = 0 ;
- Ply[p] = p ;
- }
-
- for (b = 0 ; b < N_OPPS-1 ; b++) { /* b=0..N_OPPS-2 */
- for (w = b+1 ; w < N_OPPS ; w++) { /* w=b+1..N_OPPS-1 */
- Winnr = Get_Winner (b,w) ;
- Wins [Winnr]++ ;
- }
- }
-
- for (q = 0 ; q < N_OPPS ; q++) {
- for (p = 0 ; p < N_OPPS-2 ; p++) {
- if (Wins[p] < Wins[p+1]) {
- Temp = Wins[p] ;
- Wins[p] = Wins[p+1] ;
- Wins[p+1] = Temp ;
- Temp = Ply[p] ;
- Ply[p] = Ply[p+1] ;
- Ply[p+1] = Temp ;
- }
- }
- }
-
- for (i = 0 ; i < N_OPPS ; i++) {
- Pos [Ply[i]] = i ;
- }
-
- }
-
- /***************************************************************************/
-
- void Randomise_Deltas (short Deltas[N_WEIGHTS], short Position)
- {
- short w ;
- for (w = 0 ; w < N_WEIGHTS ; w++) {
- if (rand()&1) {
- Deltas[w] = Pos_Change [Position] ;
- } else {
- Deltas[w] = -Pos_Change [Position] ;
- }
- }
- }
-
- /***************************************************************************/
-
- short Get_Winner (short Black, short White)
- {
- extern Stats_t Statistics[N_PLAYERS] ;
- boolean Playing ;
-
- if ((Black < 0) || (White < 0) ||
- (Black >= N_OPPS) || (White >= N_OPPS)) {
- printf ("\nBlack = %d, White = %d",Black,White) ;
- Error_Exit ("Bad players in tournament!") ;
- }
-
- Init_Stats () ;
- Init_Genetic_Opponents (Black,White) ;
- Print_Opponents (Black,White) ;
-
- do {
- Playing = Play_The_Game (MED_SPEED,NULL_PLAYER,Black);
- } while (Playing) ;
-
- if (Statistics[BLACK_PLAYER].Games_Won >= Target_Score) {
- return (Black) ;
- } else {
- return (White) ;
- }
- }
-
- /***************************************************************************/
-